package vip.xiaonuo.biz.core.eyesnetty;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.poi.hssf.record.DVALRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import vip.xiaonuo.biz.core.cacheentity.Modules;
import vip.xiaonuo.biz.modular.eyesdata.entity.SEyesData;
import vip.xiaonuo.biz.modular.eyesdata.service.SEyesDataService;
import vip.xiaonuo.common.cache.CommonCacheOperator;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Component
public class EyesBootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {

    private static CommonCacheOperator commonCacheOperator;

    private static SEyesDataService sEyesDataService;

    @Autowired
    public void setEmployeeServer(CommonCacheOperator commonCacheOperator,SEyesDataService sEyesDataService) {
        this.commonCacheOperator = commonCacheOperator;
        this.sEyesDataService = sEyesDataService;
    }

    private int blinkOld = 100;

    private long blinkTime;


    private int count = 0;

    private int eyeTarget = 0;


    /**
     * 从服务端收到新的数据时，这个方法会在收到消息时被调用
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        commonCacheOperator.put(Modules.EYES, Modules.ON);
        try {
            JSONObject msgJson = JSONUtil.parseObj(msg);
            //System.out.println(msgJson);
            Long timestamp = msgJson.getLong("timestamp");
            JSONObject leftExData = msgJson.getJSONObject("left_ex_data");
            Integer blink = leftExData.getInt("blink");
            JSONObject stats = msgJson.getJSONObject("stats");
            //Long duration = stats.getLong("duration");
            //zs(duration,timestamp);
            JSONObject leftGaze = msgJson.getJSONObject("left_gaze");
            JSONObject jsonObject = leftGaze.getJSONObject("gaze_point");
            //System.out.println(jsonObject);
            JSONObject leftPupil = msgJson.getJSONObject("left_pupil");
            Double pupilDiameterMm = leftPupil.getDouble("pupil_diameter_mm");
            eys(blink,timestamp);
            zs(jsonObject.getDouble("x"),jsonObject.getDouble("y"),pupilDiameterMm);
            if (commonCacheOperator.get(Modules.CHECKSTATUS).equals(Modules.ON)) {
                SEyesData sEyesData = new SEyesData();
                sEyesData.setData(msgJson.toString());
                sEyesData.setTime(System.currentTimeMillis());
                sEyesData.setCheckId(Long.parseLong(commonCacheOperator.get(Modules.TASKID).toString()));
                sEyesData.setUserId(Long.parseLong(commonCacheOperator.get(Modules.USERID).toString()));
                sEyesDataService.save(sEyesData);
            }
        } catch (Exception e) {
        }
    }

    /**
     * 从服务端收到新的数据、读取完成时调用
     *
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws IOException {
        //System.out.println("channelReadComplete");
        ctx.flush();
    }

    /**
     * 当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws IOException {
        System.out.println("exceptionCaught");
        cause.printStackTrace();
        ctx.close();//抛出异常，断开与客户端的连接
    }

    private static String buf1 = "1";

    /**
     * 客户端与服务端第一次建立连接时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelActive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        System.out.println("channelActive:" + clientIp + ctx.name());
        ctx.writeAndFlush(buf1);
    }

    /**
     * 客户端与服务端 断连时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelInactive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        ctx.close(); //断开连接时，必须关闭，否则造成资源浪费
        commonCacheOperator.put(Modules.EYES, Modules.OFF);
        System.out.println("channelInactive:" + clientIp);
    }


    private void eys(int blink,Long timestamp){
        //
        if(blink == 6){
            //开始眨眼
            if(eyeTarget == 0){
                blinkTime = timestamp;
                eyeTarget = 1;
            }
        }else{
            if(eyeTarget == 1){
                //结束眨眼
                eyeTarget = 0;
                Long blinktimeOnce = timestamp - blinkTime;
                count++;
               // System.out.println("耗时 微妙" + blinktimeOnce);
                //System.out.println("眨了   " + count);

                Object o = commonCacheOperator.get(Modules.BLINKTIMES);
                JSONObject entries = JSONUtil.parseObj(o);
                //JSONArray objects = JSONUtil.parseArray(o);
                entries.putOnce(timestamp.toString(), blinktimeOnce);
                Long closeTime = 0L;
                List<String> timeOut = new ArrayList<>();
                Set<String> timeKeys = entries.keySet();
                for (String timeKey : timeKeys) {
                    long l = Long.parseLong(timeKey);
                    if(l <= timestamp - 60000000){
                        timeOut.add(timeKey);
                    }else{
                        closeTime += entries.getLong(timeKey);
                    }
                }
                for (Object timekey : timeOut) {
                    entries.remove(timekey);
                }
                commonCacheOperator.put(Modules.BLINKTIMES,entries);
                //System.out.println("一分钟内的眨眼次数：" + entries.size());
                //System.out.println("一分钟内的眨眼累计闭合时间 微秒：" + closeTime);
                commonCacheOperator.put(Modules.BLINKRATE,entries.size());
                String blinkTIMERate = String.format("%.2f", closeTime / 60000000D);
                //System.out.println(blinkTIMERate);
                commonCacheOperator.put(Modules.BLINKTIMERATE, blinkTIMERate);
                String blinkTimeTotal = String.format("%.2f", closeTime / 1000D);
                //System.out.println( "一分钟内的眨眼累计闭合时间 毫秒" + blinkTimeTotal);
                commonCacheOperator.put(Modules.BLINKTIMETOTAL, blinkTimeTotal);
            }
        }
        Long closeTime = 0L;
        Object o = commonCacheOperator.get(Modules.BLINKTIMES);
        JSONObject entries = JSONUtil.parseObj(o);
        List<String> timeOut = new ArrayList<>();
        Set<String> timeKeys = entries.keySet();
        for (String timeKey : timeKeys) {
            long l = Long.parseLong(timeKey);
            if(l <= timestamp - 60000000){
                timeOut.add(timeKey);
            }else{
                closeTime += entries.getLong(timeKey);
            }
        }
        for (Object timekey : timeOut) {
            entries.remove(timekey);
        }
        commonCacheOperator.put(Modules.BLINKTIMES,entries);
        commonCacheOperator.put(Modules.BLINKRATE,entries.size());
        String blinkTIMERate = String.format("%.2f", closeTime / 60000000D);
        commonCacheOperator.put(Modules.BLINKTIMERATE, blinkTIMERate);
        String blinkTimeTotal = String.format("%.2f", closeTime / 1000D);
        commonCacheOperator.put(Modules.BLINKTIMETOTAL, blinkTimeTotal);

        blinkOld =  blink;
    }
    public static double sumDoubles(JSONArray jsonArray) {
        double sum = 0;
        for (int i = 0; i < jsonArray.size(); i++) {
            try {
                sum += jsonArray.getDouble(i);
            } catch (Exception e) {
                // 处理可能的异常情况
            }
        }
        return sum;
    }



    private void zs(Double x,Double y,Double pupilDiameterMm){
        Object eyesCloseStartTime = commonCacheOperator.get("eyesCloseStartTime");
        Object status = commonCacheOperator.get("eyesCloseStatus");
        if(x == 0 ){
            if(Integer.parseInt(status.toString()) == 0){
                //
                commonCacheOperator.put("eyesCloseStartTime",System.currentTimeMillis());
                commonCacheOperator.put("eyesCloseStatus",1);
            }
            return;
        }else{
            //睁眼
            if(Integer.parseInt(status.toString()) == 1){
                // 计算时间
                if(System.currentTimeMillis() - Long.parseLong(eyesCloseStartTime.toString()) >= 20000){
                    commonCacheOperator.put("eyesClose15time",System.currentTimeMillis());
                    commonCacheOperator.put("eyesCloseStatus",0);
                }
            }

        }
        Double x1 = Double.parseDouble(String.valueOf(commonCacheOperator.get(Modules.x)));
        Double y1 = Double.parseDouble(String.valueOf(commonCacheOperator.get(Modules.y)));
        if(x1 == 0){
            commonCacheOperator.put(Modules.x,x);
            commonCacheOperator.put(Modules.y,y);
            return;
        }
        Object eyesdistanceList = commonCacheOperator.get("eyesdistance");
        JSONArray eyesdistanceArr = JSONUtil.parseArray(eyesdistanceList);
        //计算得分
        double powx = Math.pow(((x - x1) * 1920), 2);
        double powy = Math.pow(((y - y1) * 1080), 2);
        double sqrt = Math.sqrt(powx + powy);
        //System.out.println( x + "  " + y);
        //System.out.println("powx powy  sqrt" + powx  + " " + powy  + " " + sqrt + " 长度" + pupilDiameterMm);
       // if(eyesdistanceArr.size() == 60){
       //     double sum = sumDoubles(eyesdistanceArr);
            Double nu = 86.633-(6.983* sqrt) +(5.858 * pupilDiameterMm);
            if(nu >= 10   && nu <= 100){
                commonCacheOperator.put(Modules.EYESALARMRESOURT,String.format("%.2f",nu));
            }

           // System.out.println(nu);
            eyesdistanceArr.clear();
            eyesdistanceArr.add(sqrt);
        //}
        if(eyesdistanceArr.size() < 60){
            eyesdistanceArr.add(sqrt);
            commonCacheOperator.put("eyesdistance",eyesdistanceArr);
        }




        Object o = commonCacheOperator.get(Modules.eyeCount);
        int i = Integer.parseInt(o.toString());
        String.format("%.6f", Math.abs(x - x1) );
       // System.out.println(String.format("%.6f", Math.abs(x - x1) ) + "           " +String.format("%.6f", Math.abs(y - y1) ));

        if(Math.abs(x - x1) <= 0.06D && Math.abs(y - y1) <= 0.06D){
            //注视开始
            if(commonCacheOperator.get(Modules.eyeStart).toString().equals("1")){
                if(i == 95){
                    //算一次走神
                    Object o1 = commonCacheOperator.get(Modules.eyeletCount);
                    Integer i1 = Integer.parseInt(o1.toString()) + 1;
                    commonCacheOperator.put(Modules.eyeletCount,i1);
                    System.out.println("走神 + 1");
                }
                int count = Integer.parseInt(o.toString()) + 1;
                commonCacheOperator.put(Modules.eyeCount,count);
            }else{
                commonCacheOperator.put(Modules.eyeStart,"1");
                commonCacheOperator.put(Modules.eyeTimes,System.currentTimeMillis());
            }
        }else{
            //停止 或者 走神结束
            if(commonCacheOperator.get(Modules.eyeStart).toString().equals("1")){
                if(i >= 95 ){
                    //走神结束
                    Long time = System.currentTimeMillis() -  Long.parseLong(commonCacheOperator.get(Modules.eyeTimes).toString());
                    //commonCacheOperator.put(Modules.eyeTimes,System.currentTimeMillis());
                    System.out.println("走神时间：" + time);
                    commonCacheOperator.put(Modules.eyeCount,0);
                    commonCacheOperator.put(Modules.eyeStart,"0");
                   if(time > Long.parseLong(String.valueOf(commonCacheOperator.get(Modules.eyeletTime)))){
                       commonCacheOperator.put(Modules.eyeletTime,time);
                       commonCacheOperator.put(Modules.eyeletTimeMin,String.format("%.2f", Double.parseDouble(time.toString()) / 1000D / 60D));
                   }

                }
            }
            commonCacheOperator.put(Modules.eyeCount,0);
            commonCacheOperator.put(Modules.eyeStart,"0");
        }
        commonCacheOperator.put(Modules.x,x);
        commonCacheOperator.put(Modules.y,y);

        return ;
    }




}
